#include "KlineLog.h"
#include <iostream>
#ifdef WIN32
#include <windows.h>
#include<direct.h> 
#include <io.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdarg.h>
#define _access access
#define _vsnprintf vsnprintf
#endif

const char *szLevel[] = { "fatal", "failed", "error", "warn", "info", "trace", "debug" };

CKlineLog::CKlineLog()
{
}


CKlineLog::~CKlineLog()
{
}

void CKlineLog::WriteLog(int loglvl, const char * format, ...)
{
	if (loglvl > m_nLogLvl)
		return;

	std::lock_guard<std::mutex> _lock(m_mutex);
	long size = file.tellp();
	if (!bInit || size >= m_nMaxSize)
	{
		bInit = false;
		if (file.is_open())
			file.close();

		std::string strOldName, strNewName;
		strOldName = m_strFile + ".log";
		strNewName = m_strFile + "_bak.log";
		if (_access(strNewName.c_str(), 6) != -1)
		{
			remove(strNewName.c_str());
		}
		rename(strOldName.c_str(), strNewName.c_str());

		file.open(strOldName.c_str(), std::ios_base::out | std::ios_base::app);
		if (!file.is_open())
			return;

		bInit = true;
	}
	std::string strDate, strTime;
	time_t now;
	struct tm *tm_now;
	time(&now);
	tm_now = localtime(&now);

	char szShow[32];

	sprintf(szShow, "%04d-%02d-%02d"
		, tm_now->tm_year + 1900, tm_now->tm_mon + 1, tm_now->tm_mday);
	strDate = szShow;

	sprintf(szShow, "%02d:%02d:%02d"
		, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
	strTime = szShow;

	char strMsg[1024];
	va_list ap;
	va_start(ap, format);
	_vsnprintf(strMsg, 1024, format, ap);
	va_end(ap);

	file << strDate.c_str() << "\t" << strTime.c_str() << "\t" << szLevel[loglvl] << "\t" << strMsg << std::endl;
	std::cout << strDate.c_str() << "\t" << strTime.c_str() << "\t" << szLevel[loglvl] << "\t" << strMsg << std::endl;
}

bool CKlineLog::InitLogEnv(const char *filename, unsigned int nLogLvl, unsigned int maxSizeMB /*= 10*/)
{
	m_nLogLvl = nLogLvl;
	m_nMaxSize = maxSizeMB * 1024 * 1024;
	m_strFile = filename;

	std::string strFileName = filename;
	std::string strPath;
#ifdef WIN32
	int nPos = strFileName.rfind("\\");
	if (nPos != -1)
	{
		strPath = strFileName.substr(0, nPos);
	}
	mkdir(strPath.c_str());

#else
	int nPos = strFileName.rfind("/");
	strPath = strFileName.substr(0, nPos);
	mkdir(strPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif
	nPos = strFileName.rfind(".");
	if (nPos != -1)
	{
		m_strFile = strFileName.substr(0, nPos);
	}
	file.open(filename, std::ios_base::out | std::ios_base::app);
	if (!file.is_open())
		return false;

	bInit = true;

	return true;
}

